package com.hefan.robot.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.Action;
import com.aliyun.openservices.ons.api.ConsumeContext;
import com.aliyun.openservices.ons.api.Message;
import com.cat.common.entity.ResultBean;
import com.cat.common.meta.ResultCode;
import com.cat.tiger.service.JedisService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hefan.common.ons.TopicRegistry;
import com.hefan.common.ons.TopicRegistryDev;
import com.hefan.common.ons.TopicRegistryTest;
import com.hefan.common.ons.listener.GLLMessageListener;
import com.hefan.common.ons.service.ONSProducer;
import com.hefan.common.util.MapUtils;
import com.hefan.live.bean.LiveRoomPersonVo;
import com.hefan.live.bean.LivingRoomInfoVo;
import com.hefan.live.bean.RobotListenerVo;
import com.hefan.live.itf.LiveLogService;
import com.hefan.live.itf.LivingRedisOptService;
import com.hefan.live.itf.RoomEnterExitOptService;
import com.hefan.robot.common.util.RandomUtil;
import com.hefan.robot.configCenter.RobotConfigCenter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * Created by nigle on 2016/12/13.
 */
@Component
public class RobotEnterExitRoomListener implements GLLMessageListener {

    Logger logger = LoggerFactory.getLogger(RobotEnterExitRoomListener.class);

    @Resource
    RoomEnterExitOptService roomEnterExitOptService;
    @Resource
    LivingRedisOptService livingRedisOptService;
    @Resource
    LiveLogService liveLogService;
    @Resource
    ONSProducer onsProducer;
    @Resource
    private RobotConfigCenter robotConfigCenter;
    @Resource
    private JedisService jedisService;

    @Override
    public TopicRegistry getTopicRegistry() {
        return TopicRegistry.HEFAN_ROBOT_ENTER_EXIT_DELAY ;
    }

    @Override
    public TopicRegistryDev getTopicRegistryDev() {
        return TopicRegistryDev.HEFAN_ROBOT_ENTER_EXIT_DELAY_DEV;
    }

    @Override
    public TopicRegistryTest getTopicRegistryTest() {
        return TopicRegistryTest.HEFAN_ROBOT_ENTER_EXIT_DELAY_TEST;
    }

    /**
     * 机器人进出直播间
     * */
    @Override
    public Action consume(Message message, ConsumeContext consumeContext) {
        String realTopic = message.getTag();
        logger.info("机器人进出直播间-开始： receiver MessageListener topic: {}, realTopic : {}, msg_body: {}",
                message.getTopic(), realTopic, new String(message.getBody()));
        try {
            Map map = new ObjectMapper().readValue(message.getBody(), Map.class);
            if (null != map && !map.isEmpty()) {
                String voStr = (String) map.get("vo");
                RobotListenerVo vo = JSONObject.parseObject(voStr, RobotListenerVo.class);
                if (null == vo) {
                    logger.error("RobotListenerVo解析失败");
                    return Action.CommitMessage;
                }
                if (!livingRedisOptService.isExistsLivingInfo_Hash(vo.getAnchId())){
                    logger.info("直播{}已经结束，结束机器人进出",vo.getAnchId());
                    return Action.CommitMessage;
                }
                String str = livingRedisOptService.getLivingInfo_Hash(vo.getAnchId());
                if (StringUtils.isBlank(str)) {
                    logger.error("直播信息获取失败");
                    return Action.CommitMessage;
                }
                LivingRoomInfoVo livingVo = JSON.parseObject(str, LivingRoomInfoVo.class);
                if (null == livingVo) {
                    logger.error("直播信息解析失败");
                    return Action.CommitMessage;
                }
                if (!livingVo.getLiveUuid().equals(vo.getLiveUuid())) {
                    logger.info("直播{}已经结束，结束机器人进出",vo.getAnchId());
                    return Action.CommitMessage;
                }
                if (vo.getInOrOut() == 1) {
                    return enterRoom(vo.getLiveUuid(), vo.getChatRoomId(), vo.getAnchId(), vo.getInfo());
                } else {
                    return exitRoom(vo.getLiveUuid(), vo.getChatRoomId(), vo.getAnchId(), vo.getInfo());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("机器人进出直播间-HEFAN_ROBOT_ENTER_EXIT_DELAY-ERROR：" + e.getMessage());
            return Action.CommitMessage;
        } finally {
            logger.info("机器人进出直播间-结束");
            return Action.CommitMessage;
        }
    }

    /**
     * 进入直播间
     */
    private Action enterRoom(String liveUuid, int chatRoomId, String anchId, String info) {
        logger.info("进入直播间{}：：开始", anchId);
        //从全局栈中取机器人
        String robotInfoStr = "";
        String userId;
        LiveRoomPersonVo robotVo = null;
        try {
            userId = livingRedisOptService.getRobotIdInAll();
            if (StringUtils.isBlank(userId)) {
                logger.error("机器人存量不足或者redis操作失败");
                return Action.CommitMessage;
            }
            logger.info("机器人ID：{}",userId);
            robotInfoStr = livingRedisOptService.getRobotInfoInAll(userId);
            if (StringUtils.isBlank(robotInfoStr)) {
                logger.error("机器人信息未找到或者redis操作失败");
                return Action.CommitMessage;
            }
            logger.info("robotInfoStr:{}",robotInfoStr);
            robotVo = JSON.parseObject(robotInfoStr, LiveRoomPersonVo.class);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("机器人进入直播间，解析失败");
        }
        if (null == robotVo) {
            logger.error("机器人进入直播间，解析为null");
            return Action.CommitMessage;
        }
        logger.info("机器人消费过滤info:{},robotVo:{}",info,JSON.toJSONString(robotVo));
        //机器人进入直播间
        ResultBean rb = roomEnterExitOptService.enterRoom(robotVo, liveUuid, chatRoomId, anchId, "");
        logger.info("进入直播间rb：{}",JSON.toJSONString(rb));
        if (null != rb && rb.getCode() == ResultCode.SUCCESS.get_code()) {
            logger.info("{}进入直播间{}---成功", robotVo.getUserId(), anchId);
            // 存入直播间内的机器人栈
            long l = livingRedisOptService.addLivingRobot(anchId, robotVo.getUserId());
            logger.info("{}进入直播间{},存入直播间机器人栈影响行数{}", robotVo.getUserId(), anchId, l);

            //记录机器人位置
            l = recordRobotLocation(robotVo.getUserId(), anchId);
            logger.info("机器人位置记录：{}",l);

            // 更新直播间实际观看人次
            long watchNuminRdeis = livingRedisOptService.addLivingWatchNum(liveUuid, 1);
            if (watchNuminRdeis > 0 && watchNuminRdeis % 100 == 0) {
                liveLogService.changeWatchNum(liveUuid, chatRoomId, 100);
            }

            Map<String, String> propty = robotConfigCenter.getPublicConfig();
            //机器人首次点亮的延时时间，单位毫秒
            long delayTimeMin = MapUtils.getLongValue(propty, "robot.first.light.delay.time.min", 0);
            long delayTimeMax = MapUtils.getLongValue(propty, "robot.first.light.delay.time.max", 0);
            long lightDelayTime = RandomUtil.getRandom(delayTimeMin, delayTimeMax + 1);
            //机器人关注主播延时时间，单位毫秒
//            delayTimeMin = MapUtils.getLongValue(propty, "robot.watch.delay.time.min", 0);
//            delayTimeMax = MapUtils.getLongValue(propty, "robot.watch.delay.time.max", 0);
//            long watchDelayTime = RandomUtil.getRandom(delayTimeMin, delayTimeMax );
            //限制机器人动作数量阈值
            long robotActionMax = MapUtils.getLongValue(propty, "robot.action.max", 500);
            //通道选择
            String onsEnv = MapUtils.getStrValue(propty, "ons.env", "");
            if (null == onsEnv) {
                logger.error("onsEnv 渠道获取失败");
            }
            //用户进入直播间队列消息发送 是否更新用户列表(异步）
            sendEnterRoomMsgQueue(anchId, chatRoomId, liveUuid, robotVo.getUserId(),
                    robotVo.getUserType(), robotVo.getUserLevel(), robotVo.getNickName(), robotVo.getHeadImg());
            //logger.info("%%%%进入-anchId:{},chatroomid:{},liveuuid:{},userid:{},userType:{},userLevel:{},nickname:{},headImg:{}", anchId, chatRoomId, liveUuid, robotVo.getUserId(), robotVo.getUserType(), robotVo.getUserLevel(), robotVo.getNickName(), robotVo.getHeadImg());
            logger.info("机器人消费过滤--success");
            long numReal = livingRedisOptService.getLivingUserCountReal(anchId);
            if (numReal < robotActionMax) {
                //发送首次点亮MQ
                firstLightRoom(robotVo, anchId, liveUuid, chatRoomId, lightDelayTime, onsEnv);
                logger.info("发送首次点亮MQ,延时{}毫秒", lightDelayTime);
                //发送关注主播MQ
//                watchAnchor(robotVo, anchId, liveUuid, chatRoomId, watchDelayTime,onsEnv);
//                logger.info("发送关注主播MQ,延时{}毫秒", watchDelayTime);
            } else {
                logger.info("直播间人数已经达到{}，停止机器人动作", numReal);
            }
        } else {
            // 进入直播间失败，归还机器人到全局栈
            long l = livingRedisOptService.returnRobotIdToAll(robotVo.getUserId());
            logger.info("{}进入直播间{}---失败---机器人信息归还全局栈影响行数{}", robotVo.getUserId(), anchId, l);
            //记录机器人位置
            l = recordRobotLocation(robotVo.getUserId(), "0");
            logger.info("机器人位置记录：{}", l);
            logger.info("机器人消费过滤--error");
        }
        return Action.CommitMessage;
    }

    /**
     * 离开直播间
     */
    private Action exitRoom(String liveUuid, int chatRoomId, String anchId, String info) {
        logger.info("移除直播间{}机器人---开始", anchId);
        long l;
            String userId = livingRedisOptService.removeLivingRobot(anchId);
            if (StringUtils.isBlank(userId)) {
                logger.error("直播间机器人为空");
                return Action.CommitMessage;
            }
        logger.info("机器人消费过滤info:{},robotVo:{}",info,userId);
        ResultBean rb = roomEnterExitOptService.exitRoom(userId, chatRoomId, liveUuid, anchId);
        if (null != rb && rb.getCode() == ResultCode.SUCCESS.get_code()) {
            logger.info("{}成功离开直播间{}", userId, anchId);
            //机器人归全局栈
            l = livingRedisOptService.returnRobotIdToAll(userId);
            logger.info("机器人{}归还全局栈，影响行数{}", userId, l);
//            Map<String, String> propty = robotConfigCenter.getPublicConfig();
            //用户离开直播间队列消息发送
            sendExitRoomMsgQueue(anchId, chatRoomId, liveUuid, userId);
            //记录机器人位置
            l = recordRobotLocation(userId, "0");
            logger.info("机器人位置记录：{}",l);
            logger.info("机器人消费过滤info:{}--success", info);
        } else {
            //离开房间失败，归还机器人到房间栈
            l = livingRedisOptService.addLivingRobot(anchId, userId);
            logger.info("离开失败，机器人{}归还房间{}栈，影响行数{}", userId, anchId, l);
            //记录机器人位置
            l = recordRobotLocation(userId, anchId);
            logger.info("机器人位置记录：{}",l);
            logger.info("机器人消费过滤info:{}--error", info);
        }
        return Action.CommitMessage;
    }

    /**
     * 进入直播间发送首页检查
     */
    @Async
    private void sendEnterRoomMsgQueue(String anchId, int chatRoomId, String liveUuid, String userId, int userType,
                                       int userLevel, String nickName, String headImg) {
        roomEnterExitOptService.sendEnterRoomMsgQueue(anchId, chatRoomId, liveUuid, userId,userType,userLevel,nickName,headImg);
    }

    /**
     * 离开直播间发送首页检查
     */
    @Async
    private void sendExitRoomMsgQueue(String anchId, int chatRoomId, String liveUuid, String userId){
        roomEnterExitOptService.sendExitRoomMsgQueue(anchId, chatRoomId, liveUuid, userId);
    }
    /**
     * 关注主播，延时发送
     * @param robotVo 从redis中取出的机器人缓存信息
     * @param delayTime 延时发送的时间
     */
    @Async
    private void watchAnchor(LiveRoomPersonVo robotVo, String anchId, String liveUuid, int chatRoomId, long delayTime, String onsEnv) {
        try {
            RobotListenerVo vo = new RobotListenerVo();
            vo.setAnchId(anchId);
            vo.setLiveUuid(liveUuid);
            vo.setChatRoomId(chatRoomId);
            vo.setLiveRoomPersonVo(robotVo);

            com.hefan.common.ons.bean.Message message = new com.hefan.common.ons.bean.Message();
            message.put("vo", JSON.toJSONString(vo));
            message.setTopic(TopicRegistry.HEFAN_ROBOT_ACTION_WATCH_DELAY);
            message.setTag(onsEnv);
            message.setKey("WatchAnchor_" + liveUuid + "_" + robotVo.getUserId());
            onsProducer.sendDelayMsg(message, delayTime);
        } catch (Exception e) {
            logger.error(robotVo.getUserId() + "首次点亮失败,直播ID：" + liveUuid, e);
        }
    }

    /**
     * 首次点亮，延时发送
     * @param robotVo 从redis中取出的机器人缓存信息
     * @param delayTime 延时发送的时间
     */
    @Async
    private void firstLightRoom(LiveRoomPersonVo robotVo, String anchId, String liveUuid, int chatRoomId, long delayTime, String onsEnv) {
        try {
            RobotListenerVo vo = new RobotListenerVo();
            vo.setAnchId(anchId);
            vo.setLiveUuid(liveUuid);
            vo.setChatRoomId(chatRoomId);
            vo.setLiveRoomPersonVo(robotVo);

            com.hefan.common.ons.bean.Message message = new com.hefan.common.ons.bean.Message();
            message.put("vo", JSON.toJSONString(vo));
            message.setTopic(TopicRegistry.HEFAN_ROBOT_ACTION_LIGHT_DELAY);
            message.setTag(onsEnv);
            message.setKey("LightRoom_" + liveUuid + "_" + robotVo.getUserId());
            onsProducer.sendDelayMsg(message, delayTime);
        } catch (Exception e) {
            logger.error(robotVo.getUserId() + "首次点亮失败,直播ID：" + liveUuid, e);
        }
    }

    /**
     * 记录机器人位置
     * @param userId 机器人ID
     * @param anchId 主播ID，全局时为0
     */
    private long recordRobotLocation(String userId, String anchId) {
        long l = livingRedisOptService.setRobotLocation(userId, anchId);
        logger.info("记录机器人位置：userId：{}在anchId：{}", userId, anchId);
        return l;
    }
}
